<template lang="html">
  <d2-container class="area-wrapper">
    <el-row v-loading="wrapperLoading">
      <el-col :span="10">
        <el-card shadow="never" class="mr10 table-page-full">
          <div slot="header" class="card-header fbc">
            <span>地区列表</span>
            <el-button v-has="'areaAdd'" type="text" @click="doAdd()">新增</el-button>
          </div>

          <div class="tree-wrapper">
            <el-tree
              ref="areaTree"
              node-key="id"
              :highlight-current="true"
              :props="{
                children: 'childList',
                label: 'name',
                isLeaf: 'leaf',
              }"
              :load="loadNode"
              lazy
              @node-click="handleNodeClick"
            >
              <span slot-scope="{ node, data }" class="custom-tree-node pr10 fbc">
                <span>{{ node.label }}</span>
                <span class="active">
                  <el-button
                    v-has="'areaChildAdd'"
                    type="text"
                    class="ml10"
                    @click.stop="doAdd({ node, data })"
                    >新增</el-button
                  >
                  <el-button
                    v-if="data.parentId !== '0'"
                    v-has="'areaDel'"
                    type="text"
                    class="ml10"
                    @click.stop="doDel({ node, data })"
                    >删除</el-button
                  >
                </span>
              </span></el-tree
            >
          </div>
        </el-card>
      </el-col>

      <el-col :span="14">
        <el-card shadow="never" class="table-page-full">
          <div slot="header" class="card-header fbc">
            <span>{{ isEdit ? "编辑" : "新增" }}地区</span>
            <el-button
              v-if="isEdit"
              v-has="'areaEdit'"
              type="text"
              :loading="btnLoading"
              @click="doSubmit"
              >提交</el-button
            >
            <el-button v-else v-has="'areaAdd'" type="text" :loading="btnLoading" @click="doSubmit"
              >确定</el-button
            >
          </div>

          <el-form
            ref="ruleForm"
            :model="ruleForm"
            :rules="rules"
            label-width="auto"
            class="mt20 form-wrapper"
          >
            <el-form-item label="上级地区" prop="parentName">
              <el-input v-model="ruleForm.parentName" disabled />
            </el-form-item>

            <el-form-item label="地区全称" prop="fullName">
              <el-input v-model="ruleForm.fullName" placeholder="请输入" />
            </el-form-item>

            <el-form-item label="地区名称" prop="name">
              <el-input
                v-model="ruleForm.name"
                clearable
                placeholder="请输入"
                @keyup.native="nameKeyUp"
              />
            </el-form-item>

            <el-form-item label="地区编码" prop="code">
              <el-input v-model="ruleForm.code" clearable placeholder="请输入" />
            </el-form-item>

            <el-form-item label="排序" prop="sortBy">
              <el-input-number v-model="ruleForm.sortBy" :min="1" :max="20" />
            </el-form-item>

            <el-form-item label="备注" prop="remarks">
              <el-input v-model="ruleForm.remarks" type="textarea" rows="4" placeholder="请输入" />
            </el-form-item>
          </el-form>
        </el-card>
      </el-col>
    </el-row>
  </d2-container>
</template>

<script>
import { AreaTree, AreaAdd, AreaUpdate, AreaDelete } from "api/sys/area";
import rules from "./config/rules";

export default {
  data() {
    return {
      ruleForm: {
        // 地区名称
        name: "",
        // 地区全称
        fullName: "",
        // 地区编码
        code: "",
        // 排序
        sortBy: "",
        // 备注
        remarks: "",
        // 区域层级
        type: "",
        // 上级地区
        parentName: "",
        // 上级地区id
        parentId: 0,
      },
      // 校验规则
      rules,
      // 是否为编辑
      isEdit: false,
      // 左侧容器的加载动画
      treeLoading: false,
      // 提交按钮的加载动画
      btnLoading: false,
      // 虚拟数据
      virtualData: [],
      // 大的loading
      wrapperLoading: false,
    };
  },
  created() {},
  methods: {
    /**
     * 左侧新增
     */
    async doAdd({ node, data } = {}) {
      if (data) {
        this.isEdit = false;
        const { name, subCount, id, fullName, childList } = data;
        const oldSortBy = childList ? childList.length : subCount;
        Object.assign(this.ruleForm, {
          parentName: name,
          parentId: id,
          sortBy: oldSortBy + 1,
          fullName,
          name: "",
          code: "",
          type: "",
        });
        await this.$nextTick();
        this.$refs.ruleForm.clearValidate();
        this.preFullName = fullName;
        this.currentNode = node;
      } else {
        // 最上级数据
        const sortBy = this.$refs.areaTree.root.childNodes.length + 1;
        Object.assign(this.ruleForm, {
          parentName: "",
          parentId: 0,
          sortBy,
          fullName: "",
          name: "",
          code: "",
        });
        this.currentNode = null;
      }
      await this.$nextTick();
      this.$refs.ruleForm.clearValidate();
    },
    /**
     * 地区名称离开
     */
    nameKeyUp() {
      const { name, parentId } = this.ruleForm;
      let tempName = "";
      if (parentId === 0) {
        tempName = name;
      } else {
        tempName = this.preFullName + name;
      }
      this.ruleForm.fullName = tempName;
    },
    /**
     * 地区删除
     */
    async doDel({ node, data }) {
      const { id } = data;
      await this.$myConfirm("删除该地区");
      try {
        await AreaDelete(id);
        this.$message.success("地区删除成功");
        node.parent.loaded = false;
        node.parent.expand();
        this.resetRightRuleForm();
      } catch (e) {
        console.log(e);
      }
    },
    /**
     * 重置右侧数据
     */
    async resetRightRuleForm() {
      this.ruleForm = {
        name: "",
        fullName: "",
        code: "",
        sortBy: "",
        remarks: "",
        type: "",
        parentName: "",
        parentId: 0,
      };
      await this.$nextTick();
      this.$refs.ruleForm.clearValidate();
      this.isEdit = false;
    },
    /**
     * 树节点的点击事件
     */
    handleNodeClick(data, node) {
      this.isEdit = true;
      this.$refs.ruleForm.clearValidate();
      const { fullName, name, parentId } = data;
      let parentName = "";
      if (parentId === 0) {
        parentName = "最高级";
      } else {
        if (fullName === name) {
          parentName = "中国";
        } else {
          parentName = node.parent.data.name;
        }
      }
      Object.assign(this.ruleForm, {
        ...data,
        parentName,
      });
      this.preFullName = parentId === "0" || fullName === name ? "" : fullName.replace(name, "");
      // 设置当前选中的节点对象
      this.currentNode = node;
    },
    /**
     * 获取左侧树形结构的数据
     */
    async _AreaTree({ parentId = 0 } = {}) {
      try {
        const data = await AreaTree(parentId);
        return data || [];
      } catch (e) {
        console.log(e);
      }
    },
    /**
     * 提交
     */
    doSubmit() {
      this.$refs.ruleForm.validate((valid) => {
        if (valid) {
          this.btnLoading = true;
          this.isEdit ? this._AreaUpdate() : this._AreaAdd();
        } else {
          return false;
        }
      });
    },
    /**
     * 新增
     */
    async _AreaAdd() {
      const { code, name, sortBy, parentId, type, fullName } = this.ruleForm;
      try {
        await AreaAdd({ code, name, sortBy, parentId, type, fullName });
        this.$message.success("区域新增成功");
        this.$refs.ruleForm.resetFields();
        // 刷新数据
        if (this.currentNode) {
          this.currentNode.loaded = false;
          this.currentNode.expand();
        } else {
          this.$refs.areaTree.root.loaded = false;
          this.$refs.areaTree.root.expand();
        }
      } catch (e) {
        console.log(e);
      } finally {
        this.btnLoading = false;
      }
    },
    /**
     * 编辑
     */
    async _AreaUpdate() {
      const { id, code, name, sortBy, remarks, parentId, type, fullName } = this.ruleForm;
      try {
        await AreaUpdate({
          id,
          code,
          name,
          sortBy,
          remarks,
          parentId,
          type,
          fullName,
        });
        this.$message.success("区域编辑成功");
        this.$refs.ruleForm.resetFields();
        this.currentNode.parent.loaded = false;
        this.currentNode.parent.expand();
      } catch (e) {
        console.log(e);
      } finally {
        this.btnLoading = false;
      }
    },
    /**
     * 加载树形数据
     */
    async loadNode(node, resolve) {
      if (node.level === 0) {
        this.treeLoading = true;
        let data = await this._AreaTree();
        this.treeLoading = false;
        data = this.treeDataFormat(data);
        this.virtualData = data;
        return resolve(data);
      } else {
        const {
          data: { id },
        } = node;
        const data = await this._AreaTree({ parentId: id });
        // 下面两个方法是为了实时更新childNum字段，不知道为啥自己就可以了
        this.setVirtualDataChildData({ id, childList: data });
        this.resetChildNum();
        return resolve(this.treeDataFormat(data));
      }
    },
    /**
     * 设置虚拟数据集
     */
    setVirtualDataChildData({ list, id: curId, childList: curData }) {
      list = list || this.virtualData;
      for (let i = 0; i < list.length; i++) {
        const { id, childList } = list[i];
        if (curId === id) {
          list[i].childList = curData;
          break;
        }
        if (childList && childList.length) {
          this.setVirtualDataChildData({
            list: childList,
            id: curId,
            childList: curData,
          });
        }
      }
    },
    /**
     * 重置虚拟数据集中的subCountr字段
     */
    resetChildNum({ list } = {}) {
      list = list || this.virtualData;
      for (let i = 0; i < list.length; i++) {
        const { childList } = list[i];
        if (childList && childList.length) {
          list[i].subCount = childList.length;
          this.resetChildNum({
            list: childList,
          });
        }
      }
    },
    /**
     * 树形数据格式化
     */
    treeDataFormat(arr) {
      arr.map((item) => {
        item.leaf = !item.subCount;
      });
      arr.sort((a, b) => a.sortBy - b.sortBy);
      return arr;
    },
  },
};
</script>

<style lang="scss" scoped>
.area-wrapper {
  .custom-tree-node {
    flex: 1;
    &:hover {
      .active {
        display: block;
      }
    }
  }
  .tree-wrapper {
    height: calc(100vh - 178px);
  }
  .form-wrapper {
    height: calc(100vh - 198px);
  }
  .active {
    display: none;
  }
  .card-header {
    ::v-deep .el-button {
      padding: 0 !important;
    }
  }
}
</style>
